package com.portal.framework.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;

import org.apache.commons.beanutils.BeanUtils;





public class DTOUtil
{


    /**
     * 通过调用一个对象的get方法，把obj转化成一个HashMap，其关键字为该对象所对应
     * 类型中以get开头的方法名字去掉get后第一个字母小写的结果。
     *
     * @param obj
     * @return
     */
	public static HashMap Object2HashMap(Object obj) {
		if (obj == null) {
			return null;
		}
		HashMap hm = null;
		try {
			hm = new HashMap(BeanUtils.describe(obj));
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		if (hm != null) {
			hm.remove("class");
		}
		return hm;
	}

    /**
     * 通过调用cls中的set方法，把一个HashMap转化成类型为cls的对象，
     *
     * @param hm
     * @param cls
     * @return
     */
	public static Object HashMap2Object(HashMap hm, Class cls) {
		try {
			Object oBean = cls.newInstance();

			BeanUtils.populate(oBean, hm);
			return oBean;
		} catch (Exception e) {
			return null;
		}
	}

    /**
     * 把源srcObj的属性的值付给cls相同的属性上
     * @param srcObj
     * @param cls
     * @return
     */
	public static Object changeObjectToObject(Object srcObj, Class cls) {
		try {
			Object retObj = cls.newInstance();
			HashMap hm = DTOUtil.Object2HashMap(srcObj);
			BeanUtils.populate(retObj, hm);
			return retObj;
		} catch (Exception e) {
			return null;
		}
	}

    /**
     * 根据方法名获取方法对象
     * @param c  方法所属的类
     * @param methodName 方法名
     * @return 方法对象
     */
	public static Method getMethod(Class c, String methodName) {
		Method aMethod = null;
		try {
			Method m[] = c.getMethods();
			for (int i = 0; i < m.length; i++) {
				if (m[i].getName().equals(methodName)) {
					aMethod = m[i];
					break;
				}
			}
		} catch (SecurityException ex) {
			throw new RuntimeException(ex);
		}
		return aMethod;
	}

    /**
     * 判断一个对象是否数字类型
     * @param value 要判断的对象
     * @return boolean
     */
	public static boolean isNumber(Object value) {
		try {
			Double.parseDouble(String.valueOf(value));
		} catch (NumberFormatException ex) {
			return false;
		}
		return true;
	}

    /**
     * 调用对象的set方法设置属性值
     * @param methodName set方法名
     * @param value 属性值
     * @param obj 待设值的对象
     */
	public static void setValue(String methodName, Object value, Object obj){
		try {
			Method aMethod = DTOUtil.getMethod(obj.getClass(), methodName);
			Object[] paras = null;
			paras = new Object[] {value};
			aMethod.invoke(obj, paras);
		} catch (Exception ex) {
            throw new RuntimeException("属性值设置异常");
		}
	}

    /**
     * 通过get方法获取属性值
     * @param methodName get方法
     * @param obj 方法所属对象
     * @return 属性值
     */
    public static Object getValue(String methodName, Object obj){
        try {
            Method aMethod = DTOUtil.getMethod(obj.getClass(), methodName);
            return aMethod.invoke(obj, null);
        } catch (Exception ex) {
            throw new RuntimeException("属性值获取异常");
        }
    }
    
    /**
     * 获取整型属性值
     * @param dto 属性所属对象
     * @param fcode 属性名
     * @return 属性值
     */
    public static int getInt(Object dto, String fcode) {
        try
        {
            Object o = getObject(dto,fcode);
            int i = Integer.valueOf(o.toString()).intValue();
            return i;
        }
        catch(Exception ex)
        {
            throw new RuntimeException("无法将对象转换为数字");
        }
    }

    /**
     * 获取字符串属性值
     * @param dto 属性所属对象
     * @param fcode 属性名
     * @return 属性值
     */
    public static String getString(Object dto, String fcode) {
        try
        {
            return (String)getObject(dto, fcode);
        }
        catch(Exception ex)
        {
            throw new RuntimeException("无法将对象转换为字符串");
        }
    }

    /**
     * 获取DTO的属性值
     * @param dto Dto对象
     * @param fcode 属性名
     * @return 属性值
     */
    public static Object getObject(Object dto, String fcode) {
           try
        {
            return BeanUtils.getProperty(dto, fcode);
        } catch (Exception e)
        {
            throw new RuntimeException("通过属性名获取属性值发生错误！");
        }

    }
    
    /**
     * 设置属性值
     * @param dto DTO对象
     * @param fieldName 属性名
     * @param value  属性值
     */
    public static void setValue(Object dto,String fieldName,Object value)
    {
        fieldName=fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
        try
        {
            getMethod(dto.getClass(),"set"+fieldName).invoke(dto,new Object[] {value});
        } catch (Exception ex)
        {
            throw new RuntimeException("通过反射设置属性值异常!");
        } 
        
    }
    
    /**
     * 拷贝DTO，可将父类属性也拷贝过来，DTO的属性需有getter和setter
     * @param src 源DTO
     * @param dest 目标DTO
     */
    public static void copyObject(Object src,Object dest)
    {
        if(src.getClass().equals(dest.getClass()))
        {
             Method[] methods = src.getClass().getMethods();
            String fieldName=null;
            for (int i = 0; i < methods.length; i++)
            {
              if(methods[i].getName().startsWith("set"))
              {
                  Object value;
                 try
                 {
                     value = src.getClass().getMethod("get"+methods[i].getName().substring(3),null).invoke(src,null);
                     methods[i].invoke(dest,new Object[] {value});
                 } catch (Exception e)
                 {
                     continue;
                 } 
                 
              }
            }
        }
    }

    
    public static void main(String[] args)
    {
        SQLDTO sql1 = new SQLDTO();
        sql1.setDatatype(SQLUtil.NUMBER_TYPE);
        sql1.setItem("money");
        sql1.setMinvalue("100");
        sql1.setOperator(">");
        sql1.setLogical("and");
        SQLDTO sql2=new SQLDTO();
        copyObject(sql1,sql2);
        return;
    }
    
}
